package com.ouyunc.gateway.exception;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ouyunc.common.base.ResponseResult;
import com.ouyunc.common.constant.enums.ResponseCodeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;


/**
 * @Author fangzhenxun
 * @Description: 网关全局异常处理类,注意：优先级一定要小于内置 ResponseStatusExceptionHandler 经过它处理的获取对应错误类的 响应码
 * @Version V1.0
 **/
@Configuration
@Order(-1)
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {
    private static Logger log = LoggerFactory.getLogger(GlobalExceptionConfiguration.class);


    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable e) {
        log.error("网关异常：{}", e.getMessage());
        ServerHttpResponse response = exchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(e);
        }
        ResponseCodeEnum responseCodeEnum = ResponseCodeEnum.INTERNAL_SERVER_ERROR;
        // header set
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        if (e instanceof ResponseStatusException) {
            HttpStatus status = ((ResponseStatusException) e).getStatus();
            responseCodeEnum = ResponseCodeEnum.prototype(status.value());
            response.setStatusCode(status);
        }
        // 将信息转换为 JSON
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(JSON.toJSONBytes(ResponseResult.error(responseCodeEnum), SerializerFeature.WriteMapNullValue));
        return response.writeWith(Mono.just(buffer));
    }
}
